﻿using System;
using System.Collections.Generic;
using System.Text;
using Musicman.Common;
using Musicman.DAL;
using Musicman.Common.Entities;
using System.Text.RegularExpressions;

namespace Musicman.Business
{
    public class UserManager
    {
        # region singleton definition
        static readonly UserManager instance = new UserManager();

        public static UserManager Instance
        {
            get
            {
                return instance;
            }
        }
        static UserManager()
        {
        }
        # endregion

        #region select 

        public string[] GetUserRoles(long userID)
        {
            string[] res = null;
            try
            {
                res = UserDAO.Instance.GetUserRoles(userID);
            }
            catch (Exception ex)
            {
                res = null;
                LogManager.LogException("Unable to laod user roles list ", ex);
            }
            return res;
        }

        public User LoggInUser(string email, string password, LoginType loginType)
        {
            User res = null;
            try
            {
                bool encripted = Regex.IsMatch(password, "[A-Z0-9]{2}(-[A-Z0-9]{2}){15}");
                res = UserDAO.Instance.GetUser(email, password, encripted);
                if (res != null)
                {
                    UserDAO.Instance.UpdateUserStats((long)res.Personid, loginType);
                }
            }
            catch (Exception ex)
            {
                res = null;
                LogManager.LogException("Unable to login user", ex);
            }
            return res;
        }

        public User LoggInUser(string password, LoginType loginType)
        {
            User res = null;
            try
            {
                res = UserDAO.Instance.GetUserFromPass(password);
            }
            catch (Exception ex)
            {
                res = null;
                LogManager.LogException("Unable to login user", ex);
            }
            return res;
        }

        public bool CheckMail(string email)
        {
            bool res = false;
            try
            {
                res = UserDAO.Instance.CheckEmail(email);
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to check email", ex);
            }
            return res;
        }

        public User GetUser(long userID)
        {
            return GetUser(userID, false);
        }

        public User GetUser(long userID, bool loadStats)
        {
            User res = null;
            try
            {
                res = UserDAO.Instance.GetUser(userID, loadStats);
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to load user", ex);
            }
            return res;
        }

        public long? AuthenticateUser(string email, string password)
        {
            long? res = null;
            try
            {
                bool encripted = Regex.IsMatch(password, "[A-Z0-9]{2}(-[A-Z0-9]{2}){15}");
                res = UserDAO.Instance.AuthenticateUser(email, password, encripted);
            }
            catch (Exception ex)
            {
                res = null;
                LogManager.LogException("Unable to authenticate user", ex);
            }
            return res;
        }

        public List<User> LoadTopWebLoggers(int top)
        {
            List<User> res = null;
            try
            {
                string orderBY = "ORDER BY UserStats.NUMLOGSWEB DESC";
                res = UserDAO.Instance.LoadUsers(top, "", orderBY, true, new SelectParameter[] { });
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to load top downloaders", ex);
            }
            return res;
        }

        public List<User> LoadTopLoggers(int top)
        {
            List<User> res = null;
            try
            {
                string orderBY = "ORDER BY (UserStats.NUMLOGSWEB + UserStats.NUMLOGSCLIENT) DESC";
                res = UserDAO.Instance.LoadUsers(top, "", orderBY, true, new SelectParameter[] { });
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to load top downloaders", ex);
            }
            return res;
        }

        public List<User> LoadTopDownloaders(int top)
        {
            List<User> res = null;
            try
            {
                string orderBY = "ORDER BY UserStats.TOTALFILES DESC";
                res = UserDAO.Instance.LoadUsers(top, "", orderBY, true, new SelectParameter[] { });
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to load top downloaders", ex);
            }
            return res;
        }

        public List<User> LoadMailSubscribers()
        {
            List<User> res = null;
            try
            {
                string where = " WHERE Users.MailRQ = 1 AND Users.Disabled = 0 ";
                res = UserDAO.Instance.LoadUsers(0, where, "", false, new SelectParameter[] { });
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to load subscribers", ex);
            }
            return res;
        }

        public List<User> LoadAdminUsers()
        {
            List<User> res = null;
            try
            {
                string where = " INNER JOIN Userroles Roles on Roles.userid = Users.personid WHERE Roles.Role= 'admin' AND Users.Disabled = 0 ";
                res = UserDAO.Instance.LoadUsers(0, where, "", false, new SelectParameter[] { });
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to load admin users", ex);
            }
            return res;
        }

        public List<User> LoadAllUsers()
        {
            List<User> res = null;
            try
            {
                string orderby = " ORDER BY UserStats.LastLoggedDate DESC";
                res = UserDAO.Instance.LoadUsers(0, "", orderby, true, new SelectParameter[] { });
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to load all users", ex);
            }
            return res;
        }

        public byte[] LoadProfilePicture(long userID)
        {
            byte[] res = null;
            try
            {
                res = UserDAO.Instance.LoadProfilePicture(userID);
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to load profile pictures", ex);
            }
            return res;
        }

        #endregion

        #region update

        public bool UpdateUserProfile(User user)
        {
            bool res = false;
            try
            {
                res = UserDAO.Instance.UpdateUser(user); 
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to update user profile", ex);
            }
            return res;
        }

        public bool ResetUserPassword(Guid activationCode)
        {
            bool res = false;
            try
            {
                res = UserDAO.Instance.ResetUserPassword(activationCode);
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to reset user password", ex);
            }
            return res;
        }

        public User ResetUserPassword(string email, string password)
        {
            User res = null;
            try
            {
                if (UserDAO.Instance.ResetUserPassword(email, password))
                {
                    res = UserDAO.Instance.GetUser(email);
                }
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to reset user password", ex);
            }
            return res;
        }

        public bool UpdateProfilePicture(long userID, byte[] imageData)
        {
            bool res = false;
            try
            {
                res = UserDAO.Instance.UpdateProfilePicture(userID, imageData);
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable update profile pictures", ex);
            }
            return res;
        }

        public bool UpdateLastWallVisit(long userID)
        {
            bool res = false;
            try
            {
                res = UserDAO.Instance.UpdateLastWallVisit(userID, DateTime.Now);
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable update last wall visit", ex);
            }
            return res;
        }

        public bool ActivateUser(string activationCode)
        {
            bool res = false;
            try
            {
                res = UserDAO.Instance.ActivateUser(activationCode);
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to activate user", ex);
            }
            return res;
        }

        public bool ToggleEnabled(long userID, bool enabled)
        {
            bool res = false;
            try
            {
                res = UserDAO.Instance.ToggleEnabled(userID, enabled);
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to activate user", ex);
            }
            return res;
        }

        #endregion

        #region insert
        public bool AddNewUser(User user)
        {
            bool res = false;
            try
            {
                res = UserDAO.Instance.InsertUser(user);
                res = res & UserDAO.Instance.AddUserToRole((long)user.Personid, "USER");
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to insert user", ex);
            }
            return res;
        }
        #endregion

        #region delete

        public bool DeleteUser(long personID)
        {
            bool res = false;
            try
            {
                res = UserDAO.Instance.DeleteUser(personID);
            }
            catch (Exception ex)
            {
                LogManager.LogException("Unable to delete user", ex);
            }
            return res;
        }

        #endregion
    }
}

